﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using System.Text;
using System.Net;
using System.IO;
using System.Xml.Linq;
using System.Collections.Specialized;

namespace CASFilter
{
    public class CASFilter : IHttpModule, IRequiresSessionState
    {
        /*
          <appSettings>
            <add key="cas_user_properties" value="id,name,email,dept,sex"/>      放入session中的用户信息字段名
            <add key="cas_verify_url" value="http://syn_web:8088/method.ashx"/>  通过token获取用户信息的地址
            <add key="cas_login_url" value="http://syn_web:8088/login.aspx"/>    登录地址
            <add key="cas_user_session_name" value="user"/>                      用户信息session名称
            <add key="cas_filter_except" value="request_token,"/>                不需要登录的额页面地址关键字，使用indexof裹了，注意
          </appSettings>
        */
        string cas_verify_url = System.Configuration.ConfigurationManager.AppSettings["cas_verify_url"];
        string cas_login_url = System.Configuration.ConfigurationManager.AppSettings["cas_login_url"];
        string[] properties = System.Configuration.ConfigurationManager.AppSettings["cas_user_properties"].Split(new char[] { ',' });
        string cas_user_session_name = System.Configuration.ConfigurationManager.AppSettings["cas_user_session_name"];
        string[] cas_filter_excepts = System.Configuration.ConfigurationManager.AppSettings["cas_filter_except"].Split(new char[] { ',' });

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
        }

        void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            try
            {
                HttpApplication ha = (HttpApplication)sender;

                HttpRequest Request = ha.Context.Request;
                HttpResponse Response = ha.Context.Response;

                string continue_url = Request.Url.AbsoluteUri;
                string path = ha.Context.Request.Url.AbsolutePath;

                if (filter(continue_url)) return;

                string token = Request["token"];
                if (!string.IsNullOrEmpty(token)) //这次请求是从CAS登陆后跳转而来
                {
                    //使用POST连接CAS的method.ashx，通过token获取用户信息
                    string userxml = Post(cas_verify_url, "token=" + token, "utf-8");
                    ha.Session[cas_user_session_name] = ParseUser(userxml);

                    string continute_url = ha.Session["continue_url"].ToString();
                    ha.Session.Remove("continue_url");
                    Response.Redirect(continute_url);
                }

                if ((ha.Session == null) || (ha.Session["user"] == null)) //通过Session判断登陆状态
                {
                    ha.Session["continue_url"] = continue_url;
                    ha.Response.Redirect(cas_login_url + "?continue_url=" + HttpUtility.UrlEncode(continue_url)); //去登陆cas页面
                }
            }
            catch (Exception ex)
            {
                (sender as HttpApplication).Response.Write(ex.Message);
            }
        }

        private bool filter(string url)
        {
            foreach (string u in cas_filter_excepts)
            {
                if (url.IndexOf(u) > 0)
                    return true;
            }
            return false;
        }

        private NameValueCollection ParseUser(string userxml)
        {
            XElement userroot = XElement.Parse(userxml);
            NameValueCollection userinfo = new NameValueCollection();
            foreach (string property in properties)
            {
                XElement temp = userroot.Element(property);
                if (temp != null)
                {
                    userinfo.Add(property, temp.Value);
                }
            }
            return userinfo;
        }

        public string Post(string postUrl, string postData, string chars_set)
        {
            Encoding encoding = Encoding.GetEncoding(chars_set);
            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(postUrl);
            CookieContainer cookieContainer = new CookieContainer();
            Request.CookieContainer = cookieContainer;
            Request.Method = "POST";
            Request.ContentType = "application/x-www-form-urlencoded";
            Request.AllowAutoRedirect = true;
            byte[] postdata = encoding.GetBytes(postData);
            using (Stream newStream = Request.GetRequestStream())
            {
                newStream.Write(postdata, 0, postdata.Length);
            }
            using (HttpWebResponse response = (HttpWebResponse)Request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(stream, encoding, true))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
        }
    }
}
